package com.mxpio.erp.inventory.service.impl;

import com.mxpio.erp.common.enums.OrderEnums;
import com.mxpio.erp.common.enums.OrderStatusEnums;
import com.mxpio.erp.common.inventory.entity.VInvStock;
import com.mxpio.erp.common.inventory.entity.WarehouseOrder;
import com.mxpio.erp.common.inventory.service.LotService;
import com.mxpio.erp.common.jpa.model.Order;
import com.mxpio.erp.common.jpa.model.OrderLine;
import com.mxpio.erp.common.jpa.model.OrderLineKey;
import com.mxpio.erp.common.order.policy.OrderContext;
import com.mxpio.erp.common.order.service.OrderLineService;
import com.mxpio.erp.common.purchase.entity.PurchaseOrder;
import com.mxpio.erp.common.purchase.entity.PurchaseOrderLine;
import com.mxpio.erp.common.technology.entity.Item;
import com.mxpio.erp.common.technology.entity.ItemMaterialProp;
import com.mxpio.erp.common.technology.entity.ItemStoreProp;
import com.mxpio.erp.common.technology.service.ItemService;
import com.mxpio.erp.common.technology.vo.ItemWithSubExtendsVO;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.jpa.query.SimpleCriterion;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.mxpio.erp.common.inventory.entity.WarehouseOrderLine;
import com.mxpio.erp.common.inventory.service.WarehouseOrderLineService;
import com.mxpioframework.system.service.impl.BaseServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class WarehouseOrderLineServiceImpl extends BaseServiceImpl<WarehouseOrderLine> implements WarehouseOrderLineService {
    @Autowired
    private LotService lotService;
    @Autowired
    private ItemService itemService;

    @Autowired
    private OrderLineService bizOrderLineService;
    @Override
    @Transactional(readOnly = true)
    public void handleWarehouseOrderLineQuantity(List<WarehouseOrderLine> warehouseOrderLine) {
        if (warehouseOrderLine!=null&&warehouseOrderLine.size()>0){//查询仓单行 已执行数量
            for (WarehouseOrderLine line:warehouseOrderLine){
                BigDecimal completeQuantity = lotService.getMaxQuantityByWo(line.getBizNo(), line.getLineNo());
                line.setActualQuantity(completeQuantity);
            }
        }
    }

    @Override
    @Transactional(readOnly = true)
    public void handleToleranceRangeQuantity(List<WarehouseOrderLine> warehouseOrderLine) {
        if (warehouseOrderLine!=null&&warehouseOrderLine.size()>0) {//查询仓单行 已执行数量
            Set<String> itemCodeSet = warehouseOrderLine.stream().map(WarehouseOrderLine::getItemCode).collect(Collectors.toSet());
            List<ItemStoreProp> itemStorePropList = JpaUtil.linq(ItemStoreProp.class).equal("propType", "item").in("code", itemCodeSet).list();
            if (itemStorePropList.size()>0){
                List<Item> itemList = JpaUtil.linq(Item.class).in("itemCode", itemCodeSet).list();
                Map<String, Item> itemMap = JpaUtil.index(itemList, "itemCode");
                Map<String, ItemStoreProp> itemStorePropMap = JpaUtil.index(itemStorePropList, "code");
                for (WarehouseOrderLine line:warehouseOrderLine){
                    String itemCode = line.getItemCode();
                    if (itemStorePropMap.containsKey(itemCode)){
                        ItemStoreProp itemStoreProp = itemStorePropMap.get(itemCode);
                        Item item = itemMap.get(itemCode);
                        if (itemStoreProp!=null&&itemStoreProp.getToleranceRange()!=null&&itemStoreProp.getToleranceRange().compareTo(BigDecimal.ZERO)>0){
                            BigDecimal toleranceRange = itemStoreProp.getToleranceRange().divide(new BigDecimal("100"));//转化成小数
                            Integer scale = item.getScale();//精度
                            BigDecimal lineQuantity = line.getQuantity();
                            BigDecimal toleranceRangeQuantity = lineQuantity.multiply(toleranceRange);
                            line.setToleranceRangeQuantity(toleranceRangeQuantity.setScale(scale, RoundingMode.CEILING));
                        }
                    }
                    if (line.getToleranceRangeQuantity()==null){//为空就指定为0
                        line.setToleranceRangeQuantity(BigDecimal.ZERO);
                    }
                }
            }
        }
    }

    @Override
    @Transactional
    public void handleLiveStockQuantity(List<WarehouseOrderLine> warehouseOrderLines) {//支持多个仓单明细查询
        if (CollectionUtils.isNotEmpty(warehouseOrderLines)){
            Map<String, List<WarehouseOrderLine>> groupByBizNoMap = warehouseOrderLines.stream().collect(Collectors.groupingBy(WarehouseOrderLine::getBizNo));
            for (String bizNo: groupByBizNoMap.keySet()){
                WarehouseOrder order = JpaUtil.getOne(WarehouseOrder.class, bizNo);
                if (order==null){
                    continue;
                }
                List<WarehouseOrderLine> subLines = groupByBizNoMap.get(bizNo);
                Set<String> itemCodeSet = subLines.stream().map(WarehouseOrderLine::getItemCode).collect(Collectors.toSet());
                List<VInvStock> stockList = JpaUtil.linq(VInvStock.class).equal("whCode", order.getWhCode()).in("itemCode", itemCodeSet).list();
                if (stockList.size()>0){
                    Map<Object, VInvStock> stockByItemCodeMap = JpaUtil.index(stockList, "itemCode");
                    for (WarehouseOrderLine line:subLines){
                        if (stockByItemCodeMap.containsKey(line.getItemCode())){
                            line.setLiveStockQuantity(stockByItemCodeMap.get(line.getItemCode()).getQuantity());//关联实时可用库存
                        }else{
                            line.setLiveStockQuantity(BigDecimal.ZERO);
                        }
                    }
                }
            }
        }
    }

    @Override
    @Transactional
    public void handleTransientFields(List<WarehouseOrderLine> warehouseOrderLines) {
        Map<String, ItemWithSubExtendsVO> itemWithSubExtendsVOMap = new HashMap<>();
        for (WarehouseOrderLine line:warehouseOrderLines){
            String itemCode = line.getItemCode();
            ItemWithSubExtendsVO extendsVO = null;
            if (itemWithSubExtendsVOMap.containsKey(itemCode)){
                extendsVO = itemWithSubExtendsVOMap.get(itemCode);
            }else{
                Result<ItemWithSubExtendsVO> itemWithSubExtendsVOResult = itemService.queryItemWithExtendsByCode(itemCode);
                extendsVO = itemWithSubExtendsVOResult.getResult();
                itemWithSubExtendsVOMap.put(itemCode,extendsVO);
            }
            if (extendsVO!=null){
                ItemMaterialProp itemMaterialProp = extendsVO.getItemMaterialProp();
                if (itemMaterialProp!=null){
                    line.setMaterialType(itemMaterialProp.getMaterialType());
                    line.setMaterialDensity(itemMaterialProp.getMaterialDensity());
                    line.setMaterialDiameter(itemMaterialProp.getMaterialDiameter());
                    line.setMaterialThickness(itemMaterialProp.getMaterialThickness());
                }
                line.setMaterialBrand(extendsVO.getMaterialBrand());
            }
        }
    }

    @Override
    @Transactional
    public Page<WarehouseOrderLine> listPage(Pageable page, Criteria criteria) {
        List<Object> criterions = criteria.getCriterions();
        Iterator<Object> iterator = criterions.iterator();
        String woType = "";
        //String accessType = "";
        while (iterator.hasNext()){
            Object next = iterator.next();
            if (next instanceof SimpleCriterion){
                SimpleCriterion simpleCriterion = (SimpleCriterion) next;
                String fieldName = simpleCriterion.getFieldName();
                String value = (String) simpleCriterion.getValue();
                if ("woType".equals(fieldName)){
                    woType = value;
                    iterator.remove();
                }
                /*if ("accessType".equals(fieldName)){
                    accessType = value;
                    iterator.remove();
                }*/
            }
        }

        return JpaUtil.linq(WarehouseOrderLine.class)
                .collect("bizNo", WarehouseOrder.class, "bizNo")
                .exists(WarehouseOrder.class)
                .equalProperty("bizNo", "bizNo")
                .notEqual("closeStatus", OrderStatusEnums.CloseStatus.CLOSED.getStatusCode())
                .equal("bpmnStatus", OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode())
                .notEqual("orderStatus", OrderStatusEnums.OrderStatus.FINISHED.getStatusCode())
                .in("woType", Stream.of(woType.split(",")).collect(Collectors.toList()))
                .end()
                .where(criteria)
                .paging(page);
    }

    @Override
    @Transactional
    public Result<WarehouseOrderLine> clearOrderLine(String ids) {
        String[] id = ids.split(",");
        Set<String> bizNoSet = new HashSet<>();
        for(String key : id){
            String[] pk = key.split(":");
            OrderLineKey lineKey = new OrderLineKey();
            lineKey.setBizNo(pk[0]);
            lineKey.setLineNo(pk[1]);
            WarehouseOrderLine bizOrderLine = JpaUtil.getOne(WarehouseOrderLine.class, lineKey);
            if (StringUtils.equals(bizOrderLine.getCloseStatus(), OrderStatusEnums.CloseStatus.OPEN.getStatusCode())){
                bizOrderLine.setCloseStatus(OrderStatusEnums.CloseStatus.CLOSED.getStatusCode());
                this.update(bizOrderLine);
                bizNoSet.add(bizOrderLine.getBizNo());
            }
        }
        //判断单据明细行执行状态，是否更新仓单订单完成状态
        for (String bizNo : bizNoSet){
            WarehouseOrder order = JpaUtil.getOne(WarehouseOrder.class, bizNo);
            if (order!=null){
                boolean completion = judgeWOCompletion(order);
                if (completion){
                    order.setOrderStatus(OrderStatusEnums.OrderStatus.FINISHED.getStatusCode());
                    JpaUtil.update(order);
                }
            }
        }
        return Result.OK();
    }

    private boolean judgeWOCompletion(WarehouseOrder order){//判断仓单是否已执行完毕
        List<WarehouseOrderLine> lines = JpaUtil.linq(WarehouseOrderLine.class).equal("bizNo", order.getBizNo())
                .equal("closeStatus", OrderStatusEnums.CloseStatus.OPEN.getStatusCode()).list();
        if (lines.size()>0){
            for (WarehouseOrderLine line:lines){
                BigDecimal completeQuantity = lotService.getMaxQuantityByWo(line.getBizNo(), line.getLineNo());
                if (line.getQuantity().compareTo(completeQuantity)!=0){
                    return false;
                }
            }
        }else{
            return true;
        }
        return true;
    }
}
